/*
 * Copyright (C) 2010 Szymon Dembek
 * 
 * This source code is inspired from the source code of the official Android
 * Music Widget.
 * 
 * http://android.git.kernel.org/?p=platform/packages/apps/Music.git
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.demboos.galaxy.music.widget;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.RemoteViews;

/**
 * Simple widget to show currently playing album art along with play/pause and
 * next track buttons.
 * 
 * @author Szymon Dembek
 */
public class GalaxyMediaAppWidgetProvider extends AppWidgetProvider {

	static final String TAG = "GalaxySMusicWidget";

	static final ComponentName THIS_APPWIDGET = new ComponentName(
			"com.demboos.galaxy.music.widget",
			"com.demboos.galaxy.music.widget.GalaxyMediaAppWidgetProvider");

	private static GalaxyMediaAppWidgetProvider sInstance;

	private static void debug(String msg) {
		Log.d(TAG, msg);
	}

	@Override
	public void onEnabled(Context context) {
		super.onEnabled(context);

		debug("widgetProvider - onEnabled");

		// starting the background service when first widget added
		startService(context);
	}

	@Override
	public void onDisabled(Context context) {
		super.onDisabled(context);

		debug("widgetProvider - onDisabled");

		// stopping the background service when last widget removed
		stopService(context);
	}
	
	@Override
	public void onDeleted(Context context, int[] appWidgetIds) {
		super.onDeleted(context, appWidgetIds);
		
		debug("widgetProvider - onDeleted");
		
		// removing config for deleted widget instance
		for (int id: appWidgetIds) {
			WidgetConfigDatabase.delLayoutKey(context, id);
		}
	}

	@Override
	public void onUpdate(Context context, AppWidgetManager appWidgetManager,
			int[] appWidgetIds) {
		debug("widgetProvider - onUpdate");

		defaultAppWidget(context, appWidgetIds);
	}
	
	private static void startService(Context context) {
		// starting the service again, in case it was terminated
		Intent intent = new Intent(context, GalaxyMediaPlaybackService.class);
		context.startService(intent);
	}
	
	private static void stopService(Context context) {
		Intent intent = new Intent(context, GalaxyMediaPlaybackService.class);
		context.stopService(intent);
	}
	
	private static void sendUpdateRequest(Context context, int[] appWidgetIds) {
		// Send broadcast intent to a running GalaxyMediaPlaybackService so it
		// can
		// wrap around with an immediate update.
		Intent updateIntent = new Intent(GalaxyMediaPlaybackService.SERVICECMDX);
		updateIntent.putExtra(GalaxyMediaPlaybackService.CMDNAME,
				GalaxyMediaPlaybackService.CMDAPPWIDGETUPDATE);
		updateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,
				appWidgetIds);
		updateIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);

		context.sendBroadcast(updateIntent);
	}

	public static void defaultAppWidget(Context context, int[] appWidgetIds) {
		// initializing the widget with default layout
		debug("widgetProvider - defaultAppWidget");

		Resources res = context.getResources();
		for (int id: appWidgetIds) {
			RemoteViews views = new RemoteViews(context.getPackageName(),
					WidgetConfigDatabase.getLayoutKey(context, id));
			
			views.setViewVisibility(R.id.title, View.GONE);
			views.setTextViewText(R.id.artist, res.getText(R.string.emptyplaylist));
			
			pushUpdate(context, new int[] {id} , views);
		}		
		
		startService(context);

		sendUpdateRequest(context, appWidgetIds);
	}

	private static void pushUpdate(Context context, int[] appWidgetIds,
			RemoteViews views) {
		// Update specific list of appWidgetIds if given, otherwise default to
		// all
		debug("widgetProvider - pushUpdate");

		final AppWidgetManager gm = AppWidgetManager.getInstance(context);
		if (appWidgetIds != null) {
			gm.updateAppWidget(appWidgetIds, views);
		} else {
			gm.updateAppWidget(THIS_APPWIDGET, views);
		}
	}

	public void notifyChange(GalaxyMediaPlaybackService service, String what) {
		debug("widgetProvider - notifyChange, action: " + what);
		if (hasInstances(service)) {
			if (GalaxyMediaPlaybackService.PLAYBACK_COMPLETE.equals(what)
					|| GalaxyMediaPlaybackService.META_CHANGED.equals(what)
					|| GalaxyMediaPlaybackService.PLAYSTATE_CHANGED
							.equals(what)
					|| GalaxyMediaPlaybackService.SERVICE_CONNECTED
							.equals(what)) {
				performUpdate(service, null);
			}
		}
	}

	public void performUpdate(GalaxyMediaPlaybackService service,
			int[] appWidgetIds) {
		final Resources res = service.getResources();
		
		AppWidgetManager gm = AppWidgetManager.getInstance(service);
		
		if (appWidgetIds == null) {
			appWidgetIds = gm.getAppWidgetIds(THIS_APPWIDGET);
		}
		
		for (int id: appWidgetIds) {
			RemoteViews views = new RemoteViews(service.getPackageName(),
					WidgetConfigDatabase.getLayoutKey(service, id));
	
			if (!service.isPlayerCompatible()) {
				debug("widgetProvider - performUpdate, player not compatible");
	
				views.setViewVisibility(R.id.title, View.GONE);
				views.setTextViewText(R.id.artist,
						res.getText(R.string.warning_nodefaultplayer));
			} else {
				debug("widgetProvider - performUpdate, player compatible");
	
				CharSequence errorState = null;
				CharSequence titleName = null;
				CharSequence artistName = null;
	
				boolean playing = service.isPlaying();
				debug("widgetProvider - performUpdate, player playing: " + playing);
	
				if (service.isMediaReady()) {
					if (service.isCurrentMedia()) {
						debug("widgetProvider - performUpdate, no current media");
						titleName = service.getTrackName();
						artistName = service.getArtistName();
					}
	
					debug("widgetProvider - performUpdate, title: " + titleName
							+ ", artist: " + artistName);
	
					if (titleName == null) {
						errorState = res.getText(R.string.emptyplaylist);
					}
				} else {
					String status = Environment.getExternalStorageState();
					debug("widgetProvider - performUpdate, status: " + status);
					if (status.equals(Environment.MEDIA_SHARED)
							|| status.equals(Environment.MEDIA_UNMOUNTED)) {
						errorState = res.getText(R.string.sdcard_busy_title);
					} else if (status.equals(Environment.MEDIA_REMOVED)) {
						errorState = res.getText(R.string.sdcard_missing_title);
					}
				}
	
				if (errorState != null) {
					// Show error state to user
					views.setViewVisibility(R.id.title, View.GONE);
					views.setTextViewText(R.id.artist, errorState);
	
				} else {
					// show song info
					views.setViewVisibility(R.id.title, View.VISIBLE);
					views.setTextViewText(R.id.title, titleName);
					views.setTextViewText(R.id.artist, artistName);
				}
	
				if (playing) {
					views.setImageViewResource(R.id.control_play,
							R.drawable.eclair_ic_appwidget_music_pause);
				} else {
					views.setImageViewResource(R.id.control_play,
							R.drawable.eclair_ic_appwidget_music_play);
				}
	
				// Link actions buttons to intents
				linkButtons(service, views, playing, service.isCurrentMedia());
			}
	
			pushUpdate(service, new int[] {id}, views);
		}
	}

	private void linkButtons(Context context, RemoteViews views,
			boolean playerActive, boolean isMediaToPlay) {
		// Connect up various buttons and touch events
		Intent intent;
		PendingIntent pendingIntent;

		if (playerActive) {
			debug("widgetProvider - linkButtons, player active");

			intent = new Intent();
			intent.setClassName(
					GalaxyMediaPlaybackService.SAMSUNG_SERVICE_PACKAGE,
					GalaxyMediaPlaybackService.SAMSUNG_PLAYER_ACTIVITY_INTENT);
			pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
			views.setOnClickPendingIntent(R.id.album_appwidget, pendingIntent);
		} else {
			debug("widgetProvider - linkButtons, player inactive");

			intent = new Intent();
			intent.setClassName(
					GalaxyMediaPlaybackService.SAMSUNG_SERVICE_PACKAGE,
					GalaxyMediaPlaybackService.SAMSUNG_PLAYLIST_ACTIVITY_INTENT);
			pendingIntent = PendingIntent
					.getActivity(context, 0 /* no requestCode */, intent, 0 /*
																			 * no
																			 * flags
																			 */);
			views.setOnClickPendingIntent(R.id.album_appwidget, pendingIntent);
		}

		if (isMediaToPlay) {
			debug("widgetProvider - linkButtons, media available");

			intent = new Intent(
					GalaxyMediaPlaybackService.TOGGLEPAUSE_ACTION_INTERNAL);
			pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
			views.setOnClickPendingIntent(R.id.control_play, pendingIntent);

			intent = new Intent(GalaxyMediaPlaybackService.NEXT_ACTION_INTERNAL);
			pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
			views.setOnClickPendingIntent(R.id.control_next, pendingIntent);

			intent = new Intent(GalaxyMediaPlaybackService.PREV_ACTION_INTERNAL);
			pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
			views.setOnClickPendingIntent(R.id.control_prev, pendingIntent);
		} else {
			debug("widgetProvider - linkButtons, media unavailable");

			intent = new Intent();
			intent.setClassName(
					GalaxyMediaPlaybackService.SAMSUNG_SERVICE_PACKAGE,
					GalaxyMediaPlaybackService.SAMSUNG_PLAYLIST_ACTIVITY_INTENT);
			pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
			views.setOnClickPendingIntent(R.id.control_play, pendingIntent);
			views.setOnClickPendingIntent(R.id.control_next, pendingIntent);
			views.setOnClickPendingIntent(R.id.control_prev, pendingIntent);
		}
	}

	public static synchronized GalaxyMediaAppWidgetProvider getInstance() {
		if (sInstance == null) {
			sInstance = new GalaxyMediaAppWidgetProvider();
		}

		return sInstance;
	}

	private boolean hasInstances(Context context) {
		AppWidgetManager appWidgetManager = AppWidgetManager
				.getInstance(context);
		int[] appWidgetIds = appWidgetManager.getAppWidgetIds(THIS_APPWIDGET);
		return (appWidgetIds.length > 0);
	}
}
